package net.gdface.facedb;

import org.springframework.http.HttpStatus;
import org.springframework.http.InvalidMediaTypeException;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.gitee.l0km.com4j.base.BaseVolatile;
import com.gitee.l0km.com4j.base.BinaryUtils;
import com.gitee.l0km.com4j.base.ILazyInitVariable;
import com.google.common.base.MoreObjects;

import static com.google.common.base.Preconditions.*;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLConnection;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.gdface.facedb.FaceDb;
import net.gdface.facedb.db.ImageBean;

import static gu.sql2java.SimpleLog.log;

@RestController
@Api(value="/FaceDb/image",tags={"image Controller"})
@RequestMapping("/FaceDb/image")
public class ImageContolller implements CommonConstant {

	private static FaceDb instance;
	private static final ILazyInitVariable<byte[]> ERROR_IMAGE = new BaseVolatile<byte[]>(){

		@Override
		protected byte[] doGet() {
			try {
				return BinaryUtils.getBytesNotEmpty(ImageContolller.class.getResourceAsStream("/images/404.jpg"));
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}};
	
	private static final String IMAGE_BMP_VALUE = "image/bmp";

	public ImageContolller() {
	}
	@RequestMapping(value = "/{refType:\\w+}/{pk:\\w+}", method = RequestMethod.GET)
	@ApiOperation(
			value="根据提供的主键ID,返回图像数据",
			notes = "请求格式/${refType}/${pk}  \n"
			+ "比如获取MD5为e10adc3949ba59abbe56e057f20f883e的标准照路径为 '/FaceDb/image/IMAGE/e10adc3949ba59abbe56e057f20f883e'  \n"
			+"refType: 指定 pk 的引用类型,如下:  \n"
			+ "    DEFAULT: 返回 fd_image表指定的图像数据;  \n"
			+ "    IMAGE: 返回 fd_image表指定的图像数据;  \n"
			+ "    FACE: 返回 fd_face表中的image_md5字段指定的图像数据;  \n"
			+ "    FEATURE: 返回提取fd_feature表中的md5字段指定特征的图像数据(对于多张人脸图像合成的特征无效);  \n"
			+ "pk: 数据库表的主键值,根据 refType的类型不同，pk代表不同表的主键",
			httpMethod="GET",
			produces = MediaType.TEXT_PLAIN_VALUE 
					+ "," + MediaType.IMAGE_GIF_VALUE 
					+ ","+ MediaType.IMAGE_PNG_VALUE 
					+ ","+ MediaType.IMAGE_JPEG_VALUE
					+ ","+ IMAGE_BMP_VALUE)
	public ResponseEntity<byte[]> getImage(@PathVariable("refType") String refType,@PathVariable("pk") String pk) {
		checkState(instance != null,"facedbInstance is uninitizlied");
		HttpStatus httpStatus = HttpStatus.OK;
		MediaType mediaType;
		byte[] binary;
		try {
			// 检查 refType 是否有效
			RefSrcType.valueOf(MoreObjects.firstNonNull(refType,RefSrcType.DEFAULT.name()));
		} catch (IllegalArgumentException e) {
			httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
			mediaType = MediaType.TEXT_PLAIN;
			binary = String.format("INVALID refType: %s,'IMAGE','FACE','FEATURE' supported",refType).getBytes();
			return ResponseEntity.status(httpStatus).contentType(mediaType).body(binary);
		}

		ImageBean bean = instance.getImage(pk,refType);
		if(null != bean && null != (binary = instance.getImageBytes(bean.getMd5()))){
			try{
				String contentType;
				if(bean.getFormat() != null){
					contentType = URLConnection.guessContentTypeFromName("." + bean.getFormat());
				}else{
					contentType = URLConnection.guessContentTypeFromStream(new ByteArrayInputStream(binary));
				}
				mediaType = MediaType.parseMediaType(contentType);
			} catch (InvalidMediaTypeException e) {
				log("{}:{}",e.getClass().getName(),e.getMessage());
				httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
				mediaType = MediaType.TEXT_PLAIN;
				binary = String.format("INVALID contentType %s for image record %s",bean.getMd5()).getBytes();
			} catch (IOException e) {
				httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
				mediaType = MediaType.TEXT_PLAIN;
				binary = String.format("FAILT TO get contentType for image record %s,caused by IOException: %s",bean.getMd5(),e.getMessage()).getBytes();
			}

		}else{
			httpStatus = HttpStatus.NOT_FOUND;
			mediaType = MediaType.IMAGE_JPEG;
			binary = ERROR_IMAGE.get();
		}
		return ResponseEntity.status(httpStatus).contentType(mediaType).body(binary);
	}

	/**
	 * 设置{@link FaceDb}实例
	 * @param instance {@link FaceDb}实例
	 */
	public static void setInterfaceInstance(final FaceDb instance){
		ImageContolller.instance = instance;
	}

}
